import networkx as nx
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import random
import operator
import matplotlib.patches as mpatches
Pandemic modeling can be compartmentalized into different state, the simplest of which is the SI model. The model consists of two compartments, specifically:
Other variants of compartmentalized models such as SIS, SIR, SEIR exists, but to simplifiy the modeling, we will be using the SI model.
The following network attributes were selected arbitrarily:
While the beta value of 0.10 and the consideration for watts strogatz model was selected based on Professor Erika Legara's notebook.(https://github.com/eflegara/Network-Science-Lectures/blob/master/Exploring%20Social%20Distancing.ipynb)
Watts strogatz was created as the clusters of network reflects social clustering and encourages the spread of attribute in the network.
#pos = nx.fruchterman_reingold_layout(g);
N = 300
percentage = 0.05
beta = 0.10
g = nx.watts_strogatz_graph(N, 5, 0.89)
nx.set_node_attributes(g, 0, 'infected')
nx.set_node_attributes(g, 0, 'vaccinated')
nx.set_node_attributes(g, 0, 'quarantined')
#set infected nodes
for i in range (int(N*percentage)):
g.nodes(data=True)[random.choice(list(g.nodes))]['infected'] = 1
infected = {k:v for k,v in nx.get_node_attributes(g, "infected").items()
if v==1}
print(f'Initial infected people: {len(infected.values())}')
pos = nx.spring_layout(g, seed=18291)
node_colors = []
for node in g.nodes(data=True):
if node[1]['infected'] == 1:
node_colors.append('#fb1700')
else:
node_colors.append('#95c4cc')
# Plot network
plt.figure(figsize=(16, 12))
plt.axis("off")
dg_centrality = np.array(list(nx.degree_centrality(g).values()))
nx.draw_networkx_nodes(g, pos, alpha=0.75, node_color=node_colors,
node_size=dg_centrality*10_000)
nx.draw_networkx_edges(g, pos, alpha=0.30);
infected_patch = mpatches.Patch(color='#fb1700', label='infected')
healthy_patch = mpatches.Patch(color='#95c4cc', label='healthy')
plt.legend(handles=[infected_patch, healthy_patch])
plt.title('Visualization of affected nodes');
The simulation was inspired by Professor Erika Legara's agent based modeling in her notebook on social distancing (https://github.com/eflegara/Network-Science-Lectures/blob/master/Exploring%20Social%20Distancing.ipynb). Instead of implementing an object oriented agent based model, we leveraged the network attributes of nodes to define the state of the agent/nodes.
infected_list = []
g_copy = g.copy()
for time in range(10):
graph = g_copy.copy()
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1:
for edge in g_copy.edges(node[0]):
if (random.randint(0,100)/100) < beta:
graph.nodes(data=True)[edge[1]]['infected'] = 1
#node[1]['infected'] = 1
infected = {k:v for k,v
in nx.get_node_attributes(graph, "infected").items()
if v==1}
infected_list.append(len(infected))
g_copy = graph
pos = nx.spring_layout(g_copy, seed=18291)
node_colors = []
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1:
node_colors.append('#fb1700')
else:
node_colors.append('#95c4cc')
# Plot network
plt.figure(figsize=(16, 12))
plt.axis("off")
dg_centrality = np.array(list(nx.degree_centrality(g_copy).values()))
nx.draw_networkx_nodes(g_copy, pos, alpha=0.75, node_color=node_colors,
node_size=dg_centrality*10_000)
nx.draw_networkx_edges(g_copy, pos, alpha=0.30);
fig, ax = plt.subplots(figsize=(10,5))
sns.lineplot(x=range(len(infected_list)), y=infected_list, );
ax.set_title('Rate of Infection')
ax.set_xlabel('Time')
ax.set_ylabel('Number of Infected');
print(f'Number of infected nodes {infected_list[-1]}')
print(f'Percentage of infected population: {infected_list[-1]/N}')
per_day_change = np.array(infected_list[1:]) - np.array(infected_list[:-1])
From the original 0.5% of population being infected, the number of infected nodes rose up to 48.66% after 10 iterations or timesteps.
The quarantine simulation was modeled based on the notion of infected people/nodes should be quarantined. Once quarantined, the transmission of disease of the node will cease. There are few rules considered in the quarantine:
For illustration, suppose node 5 was infected on Day 1. Node 5 will not be tagged as quarantined on Day 2 and will still be able to infect other nodes based on the beta probability. Starting day 3, node 5 will be tagged as quarantined and will not be able to infect other nodes.
infected_list = []
g_copy = g.copy()
for time in range(5):
graph = g_copy.copy()
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1 and node[1]['quarantined'] == 0:
for edge in g_copy.edges(node[0]):
if (random.randint(0,100)/100) < beta:
graph.nodes(data=True)[edge[1]]['infected'] = 1
#node[1]['infected'] = 1
graph.nodes(data=True)[node[0]]['quarantined'] = 1
infected = {k:v for k,v
in nx.get_node_attributes(graph, "infected").items()
if v==1}
infected_list.append(len(infected))
g_copy = graph
pos = nx.spring_layout(g_copy, seed=18291)
node_colors = []
for node in g_copy.nodes(data=True):
if node[1]['quarantined'] == 1:
node_colors.append('#fad000')
elif node[1]['infected'] == 1:
node_colors.append('#fb1700')
else:
node_colors.append('#95c4cc')
# Plot network
plt.figure(figsize=(16, 12))
plt.axis("off")
dg_centrality = np.array(list(nx.degree_centrality(g_copy).values()))
nx.draw_networkx_nodes(g_copy, pos, alpha=0.75, node_color=node_colors,
node_size=dg_centrality*10_000)
nx.draw_networkx_edges(g_copy, pos, alpha=0.30);
fig, ax = plt.subplots(figsize=(10,5))
sns.lineplot(x=range(len(infected_list)), y=infected_list, );
ax.set_title('Rate of Infection')
ax.set_xlabel('Time')
ax.set_ylabel('Number of Infected');
print(f'Number of infected nodes {infected_list[-1]}')
print(f'Percentage of infected population: {infected_list[-1]/N}')
We can see that when infected nodes are quarantined as soon as possible, the possibility of transmission was greatly reduced. All infected nodes are quarantined by the third timestep which capped the number of infected ndoes to 21 or 7% of the population.
The network showed that prevention of transmission as early as possible can halt the spread of transmission within the network.
Research shows that fully vaccinated people are not immune to COVID-19 virus and are still able to transmit the virus to other person (CDC, 2021). To model the vaccination program, the network will still be able to infect vaccinated people, however; vaccinated people has less possibility to transmit the virus to other nodes.
Arbitrarily, we divided the beta by 20 for vaccinated nodes to signify the reduce possibility of transmission for vaccinated people.
We will be comparing two vaccination strategy. One is a randomized vaccination where randomly selected nodes will be tagged as vaccinated while another strategy targets the nodes with high degree centrality.
percentage = 0.05
infected_list = []
g_copy = g.copy()
for i in range (int(N*percentage)):
g_copy.nodes(data=True)[random.choice(list(g_copy.nodes))]['vaccinated'] = 1
for time in range(10):
graph = g_copy.copy()
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1:
for edge in g_copy.edges(node[0]):
new_beta = beta
if node[1]['vaccinated']:
new_beta = beta/20
if (random.randint(0,100)/100) < new_beta:
graph.nodes(data=True)[edge[1]]['infected'] = 1
#node[1]['infected'] = 1
graph.nodes(data=True)[node[0]]['quarantined'] = 1
infected = {k:v for k,v
in nx.get_node_attributes(graph, "infected").items()
if v==1}
infected_list.append(len(infected))
g_copy = graph
pos = nx.spring_layout(g_copy, seed=18291)
node_colors = []
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1:
node_colors.append('#fb1700')
elif node[1]['vaccinated'] == 1:
node_colors.append('#00005c')
else:
node_colors.append('#95c4cc')
# Plot network
plt.figure(figsize=(16, 12))
plt.axis("off")
dg_centrality = np.array(list(nx.degree_centrality(g_copy).values()))
nx.draw_networkx_nodes(g_copy, pos, alpha=0.75, node_color=node_colors,
node_size=dg_centrality*10_000)
nx.draw_networkx_edges(g_copy, pos, alpha=0.30);
random_list = infected_list
percentage = 0.05
infected_list = []
degree_centrality = {k: v for k, v in
sorted(dict(nx.degree_centrality(g_copy)).items(),
key=lambda item: item[1],
reverse=True)[:int(N*percentage)]}
g_copy = g.copy()
for k,v in degree_centrality.items():
g_copy.nodes(data=True)[k]['vaccinated'] = 1
for time in range(10):
graph = g_copy.copy()
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1:
for edge in g_copy.edges(node[0]):
new_beta = beta
if node[1]['vaccinated']:
new_beta = beta/20
if (random.randint(0,100)/100) < new_beta:
graph.nodes(data=True)[edge[1]]['infected'] = 1
#node[1]['infected'] = 1
graph.nodes(data=True)[node[0]]['quarantined'] = 1
infected = {k:v for k,v
in nx.get_node_attributes(graph, "infected").items()
if v==1}
infected_list.append(len(infected))
g_copy = graph
pos = nx.spring_layout(g_copy, seed=18291)
node_colors = []
for node in g_copy.nodes(data=True):
if node[1]['infected'] == 1:
node_colors.append('#fb1700')
elif node[1]['vaccinated'] == 1:
node_colors.append('#00005c')
else:
node_colors.append('#95c4cc')
# Plot network
plt.figure(figsize=(16, 12))
plt.axis("off")
dg_centrality = np.array(list(nx.degree_centrality(g_copy).values()))
nx.draw_networkx_nodes(g_copy, pos, alpha=0.75, node_color=node_colors,
node_size=dg_centrality*10_000)
nx.draw_networkx_edges(g_copy, pos, alpha=0.30);
targeted_list = infected_list
fig, ax = plt.subplots(1, 2, figsize=(15,5))
sns.lineplot(x=range(len(random_list)), y=random_list, ax=ax[0]);
ax[0].set_title('Rate of Infection of Random Vaccination')
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Number of Infected');
sns.lineplot(x=range(len(targeted_list)), y=targeted_list, ax=ax[1]);
ax[1].set_title('Rate of Infection of Targeted Vaccinatin')
ax[1].set_xlabel('Time')
ax[1].set_ylabel('Number of Infected');
print(f'Number of infected nodes - random list {random_list[-1]}')
print(f'Percentage of infected population - random list: {random_list[-1]/N}')
print('')
print(f'Number of infected nodes - targeted list {targeted_list[-1]}')
print(f'Percentage of infected population - targeted list {targeted_list[-1]/N}')
Comparing the two vaccination strategy, we can see that targeted vaccination reduces the transmission between nodes. It shows that the vaccination of people with high number of connection could strengthen the immunity and robustness of the network.
Barabasi, A. (n.d.). Network Science. Http://Networksciencebook.Com/Chapter/4#generating-Networks. Retrieved March 15, 2021, from http://networksciencebook.com/chapter/4#generating-networks
https://www.cdc.gov/coronavirus/2019-ncov/science/science-briefs/fully-vaccinated-people.html
Legara, E. (2021). Exploring Social Distancing. [Git Repository]. Retrieved from https://github.com/eflegara/Network-Science-Lectures/blob/master/Exploring%20Social%20Distancing.ipynb